<template>
  <div class="tags-container">
    <ScrollPane ref="scrollPaneRef">
      <router-link
        v-for="tag in visitedViews"
        :key="tag.path"
        :class="'tags-item ' + (isActive(tag) ? 'active' : '')"
        :data-path="tag.path"
        :to="{ path: tag.path, query: tag.query }"
        @click.middle="!isAffix(tag) ? closeSelectedTag(tag) : ''"
        @contextmenu.prevent="openTagMenu(tag, $event)"
      >
        {{ tag.meta?.title }}
        <span v-if="!isAffix(tag)" style="font-size: 15px" @click.prevent.stop="closeSelectedTag(tag)">
          <icon-close />
        </span>
      </router-link>
    </ScrollPane>
    <!-- tag标签操作菜单 -->
    <a-dropdown trigger="click" @click="handleRightMenu">
      <!-- <span class="menuTags"> <icon-menu /> </span> -->
      <MagicIcon></MagicIcon>
      <template #content>
        <a-doption @click="refreshSelectedTag(selectedTag)">
          <template #icon><icon-refresh /></template>
          <template #default>刷新</template>
        </a-doption>
        <a-doption @click="closeSelectedTag(selectedTag)">
          <template #icon><icon-close /></template>
          <template #default>关闭当前</template>
        </a-doption>
        <a-doption @click="closeOtherTags(selectedTag)">
          <template #icon><icon-eraser /></template>
          <template #default>关闭其他</template>
        </a-doption>
        <a-doption @click="closeAllTags(selectedTag)">
          <template #icon><icon-minus /></template>
          <template #default>关闭全部</template>
        </a-doption>
      </template>
    </a-dropdown>
  </div>
</template>

<script setup>
import { getCurrentInstance, nextTick, ref, watch, onMounted, watchEffect } from 'vue'
import { storeToRefs } from 'pinia'
import path from 'path-browserify'
import { useRoute, useRouter } from 'vue-router'
import { usePermissionStore } from '@/store/modules/permission'
import { useTagsViewStore } from '@/store/modules/tagsView'
import ScrollPane from './components/scrollBar.vue'
import MagicIcon from './components/tabIcons.vue'
const { proxy } = getCurrentInstance()
const router = useRouter()
const route = useRoute()

const permissionStore = usePermissionStore()
const tagsViewStore = useTagsViewStore()

let { visitedViews } = storeToRefs(tagsViewStore)
const selectedTag = ref({})
const scrollPaneRef = ref()
const left = ref(0)
const top = ref(0)
const affixTags = ref([])
const tagMenuVisible = ref(false) // 标签操作菜单显示状态

watch(
  route,
  () => {
    addTags()
    moveToCurrentTag()
  },
  {
    //初始化立即执行
    immediate: true,
  },
)

watchEffect(() => {
  if (tagMenuVisible.value) {
    document.body.addEventListener('click', closeTagMenu)
  } else {
    document.body.removeEventListener('click', closeTagMenu)
  }
})

function filterAffixTags(routes, basePath = '/') {
  let tags = []

  routes.forEach((route) => {
    if (route.meta && route.meta.affix) {
      const tagPath = path.resolve(basePath, route.path)
      tags.push({
        fullPath: tagPath,
        path: tagPath,
        name: route.name,
        meta: { ...route.meta },
      })
    }

    if (route.children) {
      const childTags = filterAffixTags(route.children, route.path)
      if (childTags.length >= 1) {
        tags = tags.concat(childTags)
      }
    }
  })
  return tags
}
function initTags() {
  const tags = filterAffixTags(permissionStore.routes)
  affixTags.value = tags
  for (const tag of tags) {
    // Must have tag name
    if (tag.name) {
      tagsViewStore.addVisitedView(tag)
    }
  }
}

function addTags() {
  if (route.name) {
    tagsViewStore.addView(route)
  }
}

function moveToCurrentTag() {
  nextTick(() => {
    for (const r of tagsViewStore.visitedViews) {
      if (r.path === route.path) {
        scrollPaneRef.value.moveToTarget(r)
        // when query is different then update
        if (r.fullPath !== route.fullPath) {
          tagsViewStore.updateVisitedView(route)
        }
      }
    }
  })
}

function isActive(tag) {
  return tag.path === route.path
}

function isAffix(tag) {
  return tag.meta && tag.meta.affix
}

function refreshSelectedTag(view) {
  tagsViewStore.delCachedView(view)
  const { fullPath } = view
  nextTick(() => {
    router.replace({ path: '/redirect' + fullPath }).catch((err) => {
      console.warn(err)
    })
  })
}

function toLastView(visitedViews, view) {
  const latestView = visitedViews.slice(-1)[0]
  if (latestView && latestView.fullPath) {
    router.push(latestView.fullPath)
  } else {
    // now the default is to redirect to the home page if there is no tags-view,
    // you can adjust it according to your needs.
    if (view.name === 'Dashboard') {
      // to reload home page
      router.replace({ path: '/redirect' + view.fullPath })
    } else {
      router.push('/')
    }
  }
}

function closeSelectedTag(view) {
  tagsViewStore.delView(view).then((res) => {
    if (isActive(view)) {
      toLastView(res.visitedViews, view)
    }
  })
}

function closeOtherTags() {
  router.push(selectedTag.value)
  // const arr = visitedViews.value.filter((i) => i.path !== view.path)
  // arr.forEach(() => {
  tagsViewStore.delOtherViews(selectedTag.value).then(() => {
    moveToCurrentTag()
  })
  // })
}

function closeAllTags(view) {
  tagsViewStore.delAllViews().then((res) => {
    toLastView(res.visitedViews, view)
  })
}

function openTagMenu(tag, e) {
  const menuMinWidth = 105

  // console.log('test', proxy?.$el)

  const offsetLeft = proxy?.$el.getBoundingClientRect().left // container margin left
  const offsetWidth = proxy?.$el.offsetWidth // container width
  const maxLeft = offsetWidth - menuMinWidth // left boundary
  const l = e.clientX - offsetLeft + 15 // 15: margin right

  if (l > maxLeft) {
    left.value = maxLeft
  } else {
    left.value = l
  }

  top.value = e.clientY
  tagMenuVisible.value = true
  selectedTag.value = tag
}
// 点击显示菜单
const handleRightMenu = (e) => {
  const menuMinWidth = 105

  const offsetLeft = proxy?.$el.getBoundingClientRect().left // container margin left
  const offsetWidth = proxy?.$el.offsetWidth // container width
  const maxLeft = offsetWidth - menuMinWidth // left boundary
  const l = e.clientX - offsetLeft + 15 // 15: margin right

  if (l > maxLeft) {
    left.value = maxLeft
  } else {
    left.value = l
  }

  top.value = e.clientY
  tagMenuVisible.value = true

  let activeIndex = 0
  visitedViews.value.forEach((item, index) => {
    if (isActive(item)) activeIndex = index
  })
  let timeout = setTimeout(() => {
    tagMenuVisible.value = true
    selectedTag.value = visitedViews.value[activeIndex]
    clearTimeout(timeout)
  }, 10)
}
function closeTagMenu() {
  tagMenuVisible.value = false
}
onMounted(() => {
  initTags()
})
</script>

<style scoped lang="less">
.tags-container {
  width: 100%;
  padding-right: @size-6;
  box-sizing: border-box;
  .tags-scroll-container {
    position: relative;
    width: 2000px;
    white-space: nowrap;
  }
  .menuTags {
    cursor: pointer;
  }

  .tags-item {
    color: @color-text-2;
    line-height: @size-default;
    text-align: center;
    background: var(--color-bg-2);
    border-radius: @border-radius-medium;
    border: @border-1 solid @color-border-2;
    display: inline-block;
    padding: 0 @size-3;
    margin-right: @size-2;
    cursor: pointer;
    &:hover {
      color: @primary-6;
    }

    &.active {
      color: @color-white;
      background-color: @primary-6;
    }
  }
}
</style>
